package org.codefilarete.stalactite.sql;

import java.sql.Savepoint;
import java.util.ArrayList;
import java.util.Collection;

/**
 * @author Guillaume Mary
 */
public class TransactionListenerCollection implements RollbackObserver, CommitObserver, TransactionListener {
	
	private Collection<TransactionListener> transactionListeners;
	
	public TransactionListenerCollection() {
		this(new ArrayList<>());
	}
	
	public TransactionListenerCollection(Collection<TransactionListener> transactionListeners) {
		this.transactionListeners = transactionListeners;
	}
	
	@Override
	public void beforeCommit() {
		transactionListeners.forEach(TransactionListener::beforeCommit);
		beforeCompletion();
	}
	
	@Override
	public void afterCommit() {
		transactionListeners.forEach(TransactionListener::afterCommit);
		afterCompletion();
	}
	
	@Override
	public void beforeRollback() {
		transactionListeners.forEach(TransactionListener::beforeRollback);
		beforeCompletion();
	}
	
	@Override
	public void afterRollback() {
		transactionListeners.forEach(TransactionListener::afterRollback);
		afterCompletion();
	}
	
	@Override
	public void beforeRollback(Savepoint savepoint) {
		transactionListeners.forEach(l -> l.beforeRollback(savepoint));
		beforeCompletion(savepoint);
	}
	
	@Override
	public void afterRollback(Savepoint savepoint) {
		transactionListeners.forEach(l -> l.afterRollback(savepoint));
		afterCompletion(savepoint);
	}
	
	@Override
	public void beforeCompletion() {
		transactionListeners.forEach(TransactionListener::beforeCompletion);
	}
	
	@Override
	public void afterCompletion() {
		transactionListeners.forEach(TransactionListener::afterCompletion);
		transactionListeners.removeIf(TransactionListener::isTemporary);
	}
	
	@Override
	public void addCommitListener(CommitListener commitListener) {
		transactionListeners.add(new TransactionListener() {
			
			@Override
			public void beforeCommit() {
				commitListener.beforeCommit();
			}
			
			@Override
			public void afterCommit() {
				commitListener.afterCommit();
			}
			
			@Override
			public void beforeCompletion() {
				// no completion to accomplish because the delegate doesn't
			}
			
			@Override
			public void afterCompletion() {
				// no completion to accomplish because the delegate doesn't
			}
			
			@Override
			public boolean isTemporary() {
				return commitListener.isTemporary();
			}
		});
	}
	
	@Override
	public void addRollbackListener(RollbackListener rollbackListener) {
		transactionListeners.add(new TransactionListener() {
			
			@Override
			public void beforeRollback() {
				rollbackListener.beforeRollback();
			}
			
			@Override
			public void afterRollback() {
				rollbackListener.afterRollback();
			}
			
			@Override
			public void beforeRollback(Savepoint savepoint) {
				rollbackListener.beforeRollback(savepoint);
			}
			
			@Override
			public void afterRollback(Savepoint savepoint) {
				rollbackListener.afterRollback(savepoint);
			}
			
			@Override
			public void beforeCompletion() {
				// no completion to accomplish because the delegate doesn't
			}
			
			@Override
			public void afterCompletion() {
				// no completion to accomplish because the delegate doesn't
			}
			
			@Override
			public boolean isTemporary() {
				return rollbackListener.isTemporary();
			}
		});
	}
}
